// ===============================
// 19.3 类型函数
// ===============================

类型函数是一种在编译期计算类型的技术, 是模板元编程的核心组成部分。

// 类型函数的基本概念
类型函数是接受一个或多个类型作为输入, 并产生一个类型作为输出的模板。
它们通常通过类模板的嵌套类型别名(typedef或using)来实现。
在C++中, 类型函数是实现编译期计算和类型转换的强大工具。

// ===============================
// 类型函数的实现方式
// ===============================
1. 基于类模板的类型函数
最基本的类型函数实现方式是通过类模板和嵌套类型: 

template<typename T>
struct RemoveConst {
    using type = T;  // 默认情况下, type就是T
};

// 特化版本处理const类型
template<typename T>
struct RemoveConst<const T> {
    using type = T;  // 对于const T, type是T
};

// 使用类型函数
RemoveConst<const int>::type x;  // 等价于int x

2. 使用别名模板简化使用
C++11引入了别名模板, 可以简化类型函数的使用: 

template<typename T>
using remove_const_t = typename RemoveConst<T>::type;

// 使用简化后的类型函数
remove_const_t<const int> x;  // 等价于int x

3. 条件类型函数
条件类型函数根据条件选择不同的类型: 

template<bool COND, typename TrueType, typename FalseType>
struct Conditional {
    using type = TrueType;
};

template<typename TrueType, typename FalseType>
struct Conditional<false, TrueType, FalseType> {
    using type = FalseType;
};

// 使用条件类型函数
Conditional<sizeof(int) >= sizeof(long), int, long>::type x;


4. 递归类型函数
类型函数可以递归定义, 处理复杂的类型转换: 

template<typename T>
struct RemoveAllExtents {
    using type = T;
};

template<typename T>
struct RemoveAllExtents<T[]> {
    using type = typename RemoveAllExtents<T>::type;
};

template<typename T, size_t N>
struct RemoveAllExtents<T[N]> {
    using type = typename RemoveAllExtents<T>::type;
};

// 使用递归类型函数
RemoveAllExtents<int[5][10]>::type x;  // 等价于int x


// =============================
// 类型函数的高级应用
// =============================
1. SFINAE (Substitution Failure Is Not An Error)
类型函数经常与SFINAE结合使用, 实现编译期的函数重载选择: 

// 检查类型是否有特定成员函数
template<typename T, typename = void>
struct HasToString : std::false_type {};

template<typename T>
struct HasToString<T, 
    std::void_t<decltype(std::declval<T>().toString())>> 
    : std::true_type {};


2. 类型特征的组合
类型函数可以组合使用, 构建复杂的类型转换: 
template<typename T>
struct RemoveReferenceAndConst {
    using type = typename RemoveConst<
                    typename std::remove_reference<T>::type
                 >::type;
};

3. 类型变换
类型函数可以实现各种类型变换, 如添加/移除引用、指针、const等: 
template<typename T>
struct AddPointer {
    using type = T*;
};

template<typename T>
struct AddReference {
    using type = T&;
};

4. 类型列表操作
类型函数可以操作类型列表, 实现编译期的列表处理: 
template<typename... Types>
struct TypeList {};

template<typename List>
struct FrontType;

template<typename First, typename... Rest>
struct FrontType<TypeList<First, Rest...>> {
    using type = First;
};

// =============================
// 类型函数的实际应用场景
// =============================
1.标准库实现: STL中的许多功能都依赖于类型函数
2.泛型编程: 实现对不同类型的统一处理
3.编译期计算: 避免运行时开销
4.类型安全: 在编译期捕获类型错误
5.代码优化: 为不同类型选择最优实现

// =============================
// 总结
// =============================
类型函数是C++模板元编程的核心工具, 它们允许在编译期对类型进行操作和转换。通过类型函数, 可以实现复杂的编译期计算、类型转换和条件逻辑, 为C++的泛型编程和模板元编程提供了强大的基础。

